Optimize interleave boolean gather#8350
Merged
Merged
Conversation
Merging this PR will not alter performance
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| 🆕 | Simulation | vortex[random/n2/nonnull] |
N/A | 132.9 µs | N/A |
| 🆕 | Simulation | vortex[random/n2/null] |
N/A | 135.7 µs | N/A |
| 🆕 | Simulation | vortex[round_robin/n2/nonnull] |
N/A | 136 µs | N/A |
| 🆕 | Simulation | vortex[round_robin/n2/null] |
N/A | 135.1 µs | N/A |
| 🆕 | Simulation | vortex[random/n64/nonnull] |
N/A | 183.2 µs | N/A |
| 🆕 | Simulation | vortex[random/n64/null] |
N/A | 199.9 µs | N/A |
Comparing claude/eager-heisenberg-fxi8wx (12a1071) with develop (5a764e6)
Footnotes
-
4 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
…terleave Extends the interleave benchmark to measure the Vortex boolean execute path against the arrow-rs `interleave` kernel on identical data, across three access patterns (random, round_robin, single_branch), for N=2 and N=4 value arrays, nullable and non-nullable. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
…ecked reads Profiling and disassembly of the gather inner loop showed the per-bit cost was dominated not by the 64-bit packing (optimal for a random gather) but by the overhead around each read: a wide `&[BitBuffer]` struct index, the redundant bounds `assert` inside `BitBuffer::value`, and on the nullable path a per-row `Option`/`Mask`-variant dispatch. Pre-validate the per-row bounds once, then hoist a raw `(ptr, bit_offset)` per value buffer and read each selected bit with `get_bit_unchecked`. Materialize each branch's validity into one full-length `BitBuffer` so the validity gather is the same uniform unchecked read. Measured ~1.2x faster non-nullable and ~1.4x nullable across random / round-robin / single-branch patterns. Also adds two two-value word-boundary regression tests exercising the gather across more than one 64-bit packing word, in the non-nullable and nullable cases, validated against the existing scalar reference oracle. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
Remove the arrow-rs `interleave` comparison arm and its input builder, keeping the Vortex-only benchmark across the random / round_robin / single_branch access patterns (N=2, N=4, nullable and non-nullable). No dependency changes: every arrow crate in vortex-array is used by the crate's own source. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
…ctor types Drop the `AsPrimitive<usize>` bound on the bool gather: dispatch both selectors over their concrete unsigned width via `match_each_unsigned_integer_ptype!` and convert to an index with a plain `as usize` on the native type, passed in as `branch_at` / `row_at` accessors. Keeps the selector loads at their native width. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
Keep only 2-child round-robin, 2-child random, and 64-child random (each nullable and non-nullable); drop the single_branch pattern and the N=4 variants. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
…> selectors Go back to the generic `gather<A: AsPrimitive<usize>, R: AsPrimitive<usize>>` with `.as_()` conversions, dropping the per-type `as usize` accessors. The trait conversion avoids the `cast_possible_truncation` lint without a scoped allow and matches the idiom used by the other bool kernels (e.g. take). Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
…tern Replace `Combo.pattern: &'static str` and the `match`/`unreachable!` on string literals with a `Pattern` enum (RoundRobin, Random), making the match exhaustive and dropping the unreachable arms. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
…lidity Validity is just another set of boolean buffers routed by the same selectors, so factor the hoisted-pointer unchecked gather into `gather_bits` and call it for both the values and the materialized per-branch validity, instead of duplicating the pointer-table build and `collect_bool` loop. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
…tructor docs The `new_unchecked` / `new_unchecked_slots` doc comments intra-doc-linked `[`Interleave::check`]`, a private item, failing `rustdoc::private_intra_doc_links` (`-D warnings`). Drop the link brackets, keeping the inline-code reference. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
e07d424 to
aae3eae
Compare
`cargo +nightly fmt --all --check` (the Rust lint job's format step) requires
per-item imports; split `use vortex_array::{array_session, ArrayRef}`.
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
robert3005
approved these changes
Jun 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR optimizes the boolean gather path in
InterleaveArrayand adds comprehensive benchmarks comparing Vortex's implementation against arrow-rs across multiple access patterns.